package springboot.service;

import lombok.extern.slf4j.Slf4j;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.order.OrderSequence;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import springboot.bean.Taskzc;
import springboot.bean.TaskzcExample;
import springboot.dao.TaskzcDAO;
import springboot.netty.NettySer;
import springboot.netty.SimpleServerHandler;
import springboot.tool.KernelTools;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class AgvService {
    public static final String V1="Vehicle-0001";
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String v1OrderName=null;
    int A1=0;int B1=0;int C1=0;int D1=0;int E1=0;int F1=0;int G1=0;
    private Date date=null;
    private Date timestamp=null;
    @Resource
    private NettySer nettySer;
    @Value("${netty.port}")
    private Integer port;

    private KernelTools km1=new KernelTools();
    private KernelTools km2=new KernelTools();
    private KernelTools km3=new KernelTools();
    @Resource
    private TaskzcDAO taskzcDAO;
    @Resource
    private RestTemplate restTemplate;

    //任务序列前半段
    private Taskzc taskzcStart=null;
    private TaskzcExample taskzcExampleStart=null;
    private TaskzcExample.Criteria criteriaStart=null;
    private List<Taskzc> listStart=null;
    //任务序列后半段
    private Taskzc taskzcEnd=null;
    private TaskzcExample taskzcExampleEnd=null;
    private TaskzcExample.Criteria criteriaEnd=null;
    private List<Taskzc> listEnd=null;
    //空托盘1
    private Taskzc taskzcPallet1=null;
    private TaskzcExample taskzcExamplePallet1=null;
    private TaskzcExample.Criteria criteriaPallet1=null;
    private List<Taskzc> listPallet1=null;
    //空托盘2
    private Taskzc taskzcPallet2=null;
    private TaskzcExample taskzcExamplePallet2=null;
    private TaskzcExample.Criteria criteriaPallet2=null;
    private List<Taskzc> listPallet2=null;

    @Scheduled(fixedDelay = 1500)
    public void createTaskInToMysqlByPLC() throws Exception {//这些成立的条件就是kernel在线
        if (SimpleServerHandler.PLC_IS_ONLINE==true){
            if (SimpleServerHandler.AGV_FORBID==0){
                //输送线任务创建，任务序列前半部分,先判断数据中有没有这个任务，没有的话就创建
                if (SimpleServerHandler.LOAD_YES==1){
                    taskzcExampleStart=new TaskzcExample();
                    criteriaStart=taskzcExampleStart.createCriteria();
                    criteriaStart.andStatusBetween(0,4);
                    criteriaStart.andStartEqualTo("1020");
                    criteriaStart.andEndIsNull();
                    listStart=taskzcDAO.selectByExample(taskzcExampleStart);
                    if (listStart.size()==0){
                        taskzcStart=new Taskzc();
                        taskzcStart.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcStart.setStart("1020");
                        taskzcStart.setStatus(0);
                        taskzcStart.setSequence("Sequence-"+UUID.randomUUID().toString());
                        date = new Date();
                        timestamp = sdf.parse(sdf.format(date));
                        taskzcStart.setStarttime(timestamp);
                        taskzcStart.setCategory(0);
                        taskzcDAO.insertSelective(taskzcStart);//name,start,status,sequence,startTime
                    }
                }
                //空托盘任务创建,内部依然要判断是哪一个空托盘，先判断数据中有没有这个任务，没有的话就创建
                if ((SimpleServerHandler.PALLET[0]==1||SimpleServerHandler.PALLET[1]==1) && SimpleServerHandler.UNLOAD_YES==1){
                    if (SimpleServerHandler.PALLET[0]==1 && SimpleServerHandler.UNLOAD_YES==1){
                        taskzcExamplePallet1=new TaskzcExample();
                        criteriaPallet1=taskzcExamplePallet1.createCriteria();
                        criteriaPallet1.andStatusBetween(0,4);
                        criteriaPallet1.andStartEqualTo("4009");
                        listPallet1=taskzcDAO.selectByExample(taskzcExamplePallet1);
                        if (listPallet1.size()==0){//创建空托盘1任务
                            taskzcPallet1=new Taskzc();
                            taskzcPallet1.setName("TASK-"+UUID.randomUUID().toString());
                            taskzcPallet1.setStart("4009");
                            taskzcPallet1.setEnd("1021");
                            taskzcPallet1.setStatus(0);
                            date = new Date();
                            timestamp = sdf.parse(sdf.format(date));
                            taskzcPallet1.setStarttime(timestamp);
                            taskzcPallet1.setCategory(2);
                            taskzcDAO.insertSelective(taskzcPallet1);//name,start,end,status,startTime
                        }
                    }else if (SimpleServerHandler.PALLET[1]==1 && SimpleServerHandler.UNLOAD_YES==1){
                        taskzcExamplePallet2=new TaskzcExample();
                        criteriaPallet2=taskzcExamplePallet2.createCriteria();
                        criteriaPallet2.andStatusBetween(0,4);
                        criteriaPallet2.andStartEqualTo("4010");
                        listPallet2=taskzcDAO.selectByExample(taskzcExamplePallet2);
                        if (listPallet2.size()==0){//创建空托盘2任务
                            taskzcPallet2=new Taskzc();
                            taskzcPallet2.setName("TASK-"+UUID.randomUUID().toString());
                            taskzcPallet2.setStart("4010");
                            taskzcPallet2.setCategory(2);
                            taskzcPallet2.setEnd("1021");
                            taskzcPallet2.setStatus(0);
                            date = new Date();
                            timestamp = sdf.parse(sdf.format(date));
                            taskzcPallet2.setStarttime(timestamp);
                            taskzcDAO.insertSelective(taskzcPallet2);//name,start,end,status,startTime
                        }
                    }
                }
            }
            //任务序列后半部分,禁用agv时,对任务序列后半部分无效
            taskzcExampleEnd=new TaskzcExample();
            criteriaEnd=taskzcExampleEnd.createCriteria();
            criteriaEnd.andStatusEqualTo(80);
            criteriaEnd.andStartEqualTo("1020");
            criteriaEnd.andEndIsNull();
            listEnd=taskzcDAO.selectByExample(taskzcExampleEnd);
            if (listEnd.size()>0){
                taskzcEnd=listEnd.get(0);//此时,判断货位来确定放哪一个货位
                if (SimpleServerHandler.PEOPLE_ENTRY_A==1){
                    if (SimpleServerHandler.STACK[0]==0){
                        taskzcEnd.setEnd("1001");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else if (SimpleServerHandler.STACK[1]==0){
                        taskzcEnd.setEnd("1002");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else if (SimpleServerHandler.STACK[2]==0){
                        taskzcEnd.setEnd("1003");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else if (SimpleServerHandler.STACK[3]==0){
                        taskzcEnd.setEnd("1004");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else {
                        log.info("A区已满,无法进行放货");
                    }
                }else if (SimpleServerHandler.PEOPLE_ENTRY_A==0){
                    if (SimpleServerHandler.STACK[4]==0){
                        taskzcEnd.setEnd("1005");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else if (SimpleServerHandler.STACK[5]==0){
                        taskzcEnd.setEnd("1006");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else if (SimpleServerHandler.STACK[6]==0){
                        taskzcEnd.setEnd("1007");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else if (SimpleServerHandler.STACK[7]==0){
                        taskzcEnd.setEnd("1008");
                        taskzcEnd.setStatus(0);
                        taskzcEnd.setCategory(1);
                        taskzcEnd.setName("TASK-"+ UUID.randomUUID().toString());
                        taskzcDAO.updateByPrimaryKey(taskzcEnd);
                    }else {
                        log.info("B区已满,无法进行放货");
                    }
                }
            }
            SimpleServerHandler.PLC_IS_ONLINE=false;//必须刷新数据之后才能做任务
        }
    }

    private Taskzc taskzcStartKM=null;
    private TaskzcExample taskzcExampleStartKM=null;
    private TaskzcExample.Criteria criteriaStartKM=null;
    private List<Taskzc> listStartKM=null;

    private Taskzc taskzcEndKM=null;
    private TaskzcExample taskzcExampleEndKM=null;
    private TaskzcExample.Criteria criteriaEndKM=null;
    private List<Taskzc> listEndKM=null;
    private TCSObjectReference<OrderSequence> kill=null;

    private Taskzc taskzcPalletKM=null;
    private TaskzcExample taskzcExamplePalletKM=null;
    private TaskzcExample.Criteria criteriaPalletKM=null;
    private List<Taskzc> listPalletKM=null;
    @Scheduled(fixedDelay = 1500)
    public void createTaskIntoKernel() throws Exception{
        //创建任务序列前半段
        taskzcExampleStartKM=new TaskzcExample();
        criteriaStartKM=taskzcExampleStartKM.createCriteria();
        criteriaStartKM.andCategoryEqualTo(0);
        criteriaStartKM.andStatusEqualTo(0);
        listStartKM=taskzcDAO.selectByExample(taskzcExampleStartKM);
        if (listStartKM.size()>0){
            taskzcStartKM=listStartKM.get(0);
            km1.CreateOrderSquenceStart(taskzcStartKM);
            taskzcStartKM.setStatus(1);
            taskzcDAO.updateByPrimaryKey(taskzcStartKM);
        }
        //创建任务序列后半段
        taskzcExampleEndKM=new TaskzcExample();
        criteriaEndKM=taskzcExampleEndKM.createCriteria();
        criteriaEndKM.andCategoryEqualTo(1);
        criteriaEndKM.andStatusEqualTo(0);
        listEndKM=taskzcDAO.selectByExample(taskzcExampleEndKM);
        if (listEndKM.size()>0){
            taskzcEndKM=listEndKM.get(0);
            kill=km1.getOrderSequence(V1);
            km1.CreateOrderSquenceEnd(taskzcEndKM,kill);
            taskzcEndKM.setStatus(1);
            taskzcDAO.updateByPrimaryKey(taskzcEndKM);
        }
        //创建空托盘任务
        taskzcExamplePalletKM=new TaskzcExample();
        criteriaPalletKM=taskzcExamplePalletKM.createCriteria();
        criteriaPalletKM.andCategoryEqualTo(2);
        criteriaPalletKM.andStatusEqualTo(0);
        listPalletKM=taskzcDAO.selectByExample(taskzcExamplePalletKM);
        if (listPalletKM.size()>0){
            taskzcPalletKM=listPalletKM.get(0);
            km1.CreateOrderOneStation(taskzcPalletKM);
            taskzcPalletKM.setStatus(1);
            taskzcDAO.updateByPrimaryKey(taskzcPalletKM);
        }
    }

    private Taskzc taskzc=null;
    private Taskzc taskzcChange=null;
    private TaskzcExample taskzcExampleChange=null;
    private TaskzcExample.Criteria criteriaChange=null;
    private List<Taskzc> listChange=null;
    @Scheduled(fixedDelay = 1200)
    public void changeTaskStatus() throws Exception {
        if (G1==0){
            v1OrderName=km2.getTranspotOrder(V1);
            A1=0;B1=0;C1=0;D1=0;E1=0;F1=0;
        }
        if(v1OrderName.startsWith("TASK")){
            String name=km2.getPropertyByOrder(v1OrderName,"name");
            if (G1==0){
                taskzcExampleChange=new TaskzcExample();
                criteriaChange=taskzcExampleChange.createCriteria();
                criteriaChange.andNameEqualTo(name);
                listChange=taskzcDAO.selectByExample(taskzcExampleChange);
                taskzc=listChange.get(0);//获得对象实例
                G1=1;
            }
            /*取货途中*/
            if(A1==0&&km2.getDriveOrderOperation(v1OrderName).startsWith("Load") &&
               km2.getDriveOrderState(v1OrderName).equals("TRAVELLING")&&
               !km2.getPosition(V1).equals(km2.getDriverOrderPoint(v1OrderName))){
                taskzcExampleChange=new TaskzcExample();
                criteriaChange=taskzcExampleChange.createCriteria();
                criteriaChange.andNameEqualTo(name);
                taskzcChange=new Taskzc();
                taskzcChange.setStatus(3);
                taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                A1=1;
            }
            /*取货中*/
            if(B1==0&&km2.getDriveOrderOperation(v1OrderName).startsWith("Load")&&
               km2.getDriveOrderState(v1OrderName).equals("TRAVELLING")&&
               km2.getPosition(V1).equals(km2.getDriverOrderPoint(v1OrderName))){
                taskzcExampleChange=new TaskzcExample();
                criteriaChange=taskzcExampleChange.createCriteria();
                criteriaChange.andNameEqualTo(name);
                taskzcChange=new Taskzc();
                taskzcChange.setStatus(4);
                taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                B1=1;
            }
            /*放货行走*/
            if(C1==0&&km2.getDriveOrderOperation(v1OrderName).startsWith("Unload")&&
               km2.getDriveOrderState(v1OrderName).equals("TRAVELLING")&&
               !km2.getPosition(V1).equals(km2.getDriverOrderPoint(v1OrderName))){
                taskzcExampleChange=new TaskzcExample();
                criteriaChange=taskzcExampleChange.createCriteria();
                criteriaChange.andNameEqualTo(name);
                taskzcChange=new Taskzc();
                taskzcChange.setStatus(6);
                taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                C1=1;
            }
            /*放货*/
            if(D1==0&&km2.getDriveOrderOperation(v1OrderName).startsWith("Unload")&&
               km2.getDriveOrderState(v1OrderName).equals("TRAVELLING")&&
               km2.getPosition(V1).equals(km2.getDriverOrderPoint(v1OrderName))){
                taskzcExampleChange=new TaskzcExample();
                criteriaChange=taskzcExampleChange.createCriteria();
                criteriaChange.andNameEqualTo(name);
                taskzcChange=new Taskzc();
                taskzcChange.setStatus(7);
                taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                D1=1;
            }
            if (km2.isLastState(v1OrderName)) {
                String v1orderStatus = km2.getOrderStatus(v1OrderName);
                if(E1==0&&v1orderStatus.equals("FINISHED")) {
                    if (taskzc.getCategory()==0){
                        taskzcExampleChange=new TaskzcExample();
                        criteriaChange=taskzcExampleChange.createCriteria();
                        criteriaChange.andNameEqualTo(name);
                        taskzcChange=new Taskzc();
                        taskzcChange.setStatus(80);
                        taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                        E1=1;
                    }else if (taskzc.getCategory()==1){
                        taskzcExampleChange=new TaskzcExample();
                        criteriaChange=taskzcExampleChange.createCriteria();
                        criteriaChange.andNameEqualTo(name);
                        taskzcChange=new Taskzc();
                        taskzcChange.setStatus(100);
                        date = new Date();
                        timestamp = sdf.parse(sdf.format(date));
                        taskzcChange.setEndtime(timestamp);
                        taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                        E1=1;
                    }else if (taskzc.getCategory()==2){
                        taskzcExampleChange=new TaskzcExample();
                        criteriaChange=taskzcExampleChange.createCriteria();
                        criteriaChange.andNameEqualTo(name);
                        taskzcChange=new Taskzc();
                        date = new Date();
                        timestamp = sdf.parse(sdf.format(date));
                        taskzcChange.setEndtime(timestamp);
                        taskzcChange.setStatus(100);
                        taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                        E1=1;
                    }
                    restTemplate.getForObject("http://localhost:9998/getCount",Object.class);
                    G1=0;
                }
                if(F1==0&&v1orderStatus.equals("FAILED")) {
                    if (taskzc.getCategory()==0){
                        taskzcExampleChange=new TaskzcExample();
                        criteriaChange=taskzcExampleChange.createCriteria();
                        criteriaChange.andNameEqualTo(name);
                        taskzcChange=new Taskzc();
                        taskzcChange.setStatus(98);
                        taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                        F1=1;
                    }else if (taskzc.getCategory()==1){
                        taskzcExampleChange=new TaskzcExample();
                        criteriaChange=taskzcExampleChange.createCriteria();
                        criteriaChange.andNameEqualTo(name);
                        taskzcChange=new Taskzc();
                        taskzcChange.setStatus(99);
                        date = new Date();
                        timestamp = sdf.parse(sdf.format(date));
                        taskzcChange.setEndtime(timestamp);
                        taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                        F1=1;
                    }else if (taskzc.getCategory()==2){
                        taskzcExampleChange=new TaskzcExample();
                        criteriaChange=taskzcExampleChange.createCriteria();
                        criteriaChange.andNameEqualTo(name);
                        taskzcChange=new Taskzc();
                        taskzcChange.setStatus(99);
                        date = new Date();
                        timestamp = sdf.parse(sdf.format(date));
                        taskzcChange.setEndtime(timestamp);
                        taskzcDAO.updateByExampleSelective(taskzcChange,taskzcExampleChange);
                        F1=1;
                    }
                    G1=0;
                }
            }
        }
    }

    private int agv_energy=0;
    private String state=null;
    private String procstate=null;
    private String level=null;
    private String orderName=null;
    @Scheduled(fixedDelay = 5000)
    public void changeAgvStatusToPLC() throws Exception{
        state= km3.getVehicleStatus("Vehicle-0001");//获得车的状态	   //state,procstate来判断状态
        procstate= km3.getProcState("Vehicle-0001");//获得当前车执行的状态(通过State与Processing state来判断)
        level= km3.getinter("Vehicle-0001");//获得该车的调用级别
        orderName=km3.getTranspotOrder("Vehicle-0001");
        if((state.equals("IDLE") && procstate.equals("IDLE") && level.equals("TO_BE_UTILIZED"))
            || (state.equals("EXECUTING") && orderName.startsWith("Park") && level.equals("TO_BE_UTILIZED"))
            ) {
            SimpleServerHandler.DATA[16]=8;
        } else if (state.equals("EXECUTING") && orderName.startsWith("TASK")) {
            SimpleServerHandler.DATA[16]=2;
        } else if (state.equals("ERROR")) {
            SimpleServerHandler.DATA[16]=1;
        } else if (state.equals("UNKNOWN")) {
            SimpleServerHandler.DATA[17]=1;
        }else if ((state.equals("EXECUTING") && orderName.startsWith("Recharge") && level.equals("TO_BE_UTILIZED"))
                || (state.equals("CHARGING") && level.equals("TO_BE_UTILIZED"))){
            SimpleServerHandler.DATA[16]=4;
        }
        agv_energy=km3.getEnergy("Vehicle-0001");
        if (agv_energy<=30){
            SimpleServerHandler.DATA[18]=1;
        }
    }
    @PostConstruct
    public void nettyStart() throws Exception {
        nettySer.start(port);
    }
}
